home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume21 / amd / part06 < prev    next >
Encoding:
Internet Message Format  |  1990-04-10  |  56.0 KB

  1. Subject:  v21i094:  An Automounter for NFS systems, Part06/13
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: f4c21c41 4b56c24e 5217246d 0db39196
  5.  
  6. Submitted-by: Jan-Simon Pendry <jsp@doc.ic.ac.uk>
  7. Posting-number: Volume 21, Issue 94
  8. Archive-name: amd/part06
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 6 (of 13)."
  17. # Contents:  INSTALL misc_rpc.c nfs_prot_xdr.c nfs_start.c nfs_stubs.c
  18. #   rpc_fwd.c
  19. # Wrapped by rsalz@papaya.bbn.com on Tue Apr 10 15:12:06 1990
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'INSTALL'\"
  23. else
  24. echo shar: Extracting \"'INSTALL'\" \(7869 characters\)
  25. sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
  26. XInstallation Notes for Amd.
  27. X
  28. XNOTE: Please read all of this before starting.
  29. X      It is not very long and may save you time in the long term.
  30. X
  31. X1.  ``Getting started...''
  32. X
  33. XIf you got this release in a shar file then run the shell script Configure in
  34. Xthe top directory.  If you got this release in a tar file then you are all
  35. Xset (though if you feel left out you can type run Configure anyway).
  36. X
  37. X2.  ``Find out what version of UN*X you are running...''
  38. X
  39. XTo install Amd you need a port for your version of UN*X.  In this directory
  40. Xare several files called os-*.h.  One of these should correspond to your
  41. Xversion of UN*X.  Look at the comments at the top of each file to determine
  42. Xwhich one applies to you.  If none of them do, then either no-one has yet
  43. Xdone a port, or your version of UN*X is so braindead that a port is not
  44. Xpossible (e.g. System V without reliable signals).  Run the program "os-type"
  45. Xin the current directory to see whether you and Amd are in agreement about
  46. Xyour operating system type.  The current known operating systems (grouped by
  47. Xarchitecture) are:
  48. X
  49. X    acis43            ACIS 4.3BSD on an IBM RT/PC
  50. X    bsd44            4.4 BSD on a Tahoe (or Vax)
  51. X    concentrix        Concentrix on an Alliant
  52. X    hlh42            4.2 BSD on HLH Orion 1/05
  53. X    hpux            HP-UX 6.* on a HP9000/300
  54. X    riscix            4.3 BSD on an Acorn Archimedes
  55. X    sos3, sos4        SunOS 3.x and 4.* on a Sun-3 and Sun-4
  56. X    u2_2            Ultrix 2.2 (or 2.*?) on a VAX
  57. X    u3_0            Ultrix 3.0 (or 3.*?) on a VAX
  58. X    umax43            4.3 BSD on an Encore Multimax
  59. X    utx32            UTX/32 Rel2.1a on a Gould (not yet complete)
  60. X    xinu43            More/BSD (4.3 BSD) on a VAX or HP9000/300
  61. X
  62. XIf you do define a new operating system type foo, you may care to create a
  63. Xfile called Makefile.foo which defines the special Makefile parameters.
  64. X
  65. X3.  ``Hacking the Makefile...''
  66. X
  67. XSome UN*X programs come with a Makefile which has to be manually configured
  68. Xfor your particular operating system and hardware.  However, Amd tries very
  69. Xhard to determine what type of machine you are using and how best to compile
  70. Xitself.  If this does not work then you will have to find some heuristic
  71. Xwhich can differentiate your configuration.  You may need to edit "arch" and
  72. X"os-type".  If you do make sure your changes can cope if /etc/motd is missing
  73. Xand please send it to the address below.
  74. X
  75. XYou may care to tailor some site specific preferences in "Makefile.com".  The
  76. Xvariables most likely to be changes are at the top.  Any changes are best put
  77. Xin the file Makefile.local (if they are applicable to all operating systems
  78. Xat your site) or Makefile.local.foo (where foo is the OS type as determined
  79. Xin part 1).
  80. X
  81. XAdditionally, some configuration options may be altered in "Makefile.config".
  82. XThis means that you should not need to edit any distributed files apart from
  83. X"Makefile.config".  As a minimum, you should check:
  84. X
  85. X* You are using the correct C compiler.  Amd, as shipped, does not use GCC.
  86. X  Note that using GCC version 1.34 or later (e.g. 1.36) gives structure
  87. X  passing problems with some parts of Sun's RPC library at least on Sun-4's.
  88. X  The current workaround is to use the system CC to compile the part of the
  89. X  automounter that gets hit by this problem.  [[This is not the same problem
  90. X  that is fixed by -fpcc-struct-return.]]  Amd contains no "register"
  91. X  declarations, so using old PCC based code generators is probably bad news.
  92. X
  93. X* The installation directory (ETC) is set up correctly.
  94. X
  95. X* If you are running tests then it may be worth switching on the DEBUG flag
  96. X  which will cause a running commentary to be printed to the log file.
  97. X
  98. X4.  ``Build the executable...''
  99. X
  100. XNow you need to compile the automounter.  To do this you type:
  101. X
  102. X    make
  103. X
  104. XIf you are porting to a new machine you may want to do:
  105. X
  106. X    make OS=foo
  107. X
  108. Xwhere foo is the name of your version of UN*X as determined in part 1, until
  109. Xyou have made the changes to os-type and/or arch.  When the compilation is
  110. Xcomplete you will end up with a program called "arch.foo/Amd".
  111. X
  112. XTry running:
  113. X
  114. X    arch.foo/Amd -v
  115. X
  116. Xand check the output.  It should look something like:
  117. X
  118. X  amd 5.1.1.6 of 90/01/10 17:30:40 Rel5.1c #0: Wed Jan 10 17:38:34 GMT 1990
  119. X  Built by jsp@elsinore.doc.ic.ac.uk for an ibm032 running acis43 (big-endian)
  120. X  Map support for: root, hesiod, error.
  121. X
  122. XMake sure the O/S and architecture types were correctly derived during the
  123. Xbuild.
  124. X
  125. XNOTE: If you are building for Ultrix 2.2 then you *may* need to use the
  126. Xsystem V make (s5make) or GNU make instead of /bin/make.  To do that run:
  127. X
  128. X    make MAKE=s5make
  129. Xor
  130. X    make MAKE=gmake
  131. X
  132. X5.  ``Installation...''
  133. X
  134. XIf you are not just testing Amd, then you can install it by typing:
  135. X
  136. X    make install
  137. X
  138. Xto install "arch.foo/Amd" in "/usr/local/etc/Amd" (or as otherwise
  139. Xmodified in part 2).
  140. X
  141. X6.  ``Update /etc/rpc''
  142. X
  143. XAmq uses Sun RPC to talk to Amd using program number 300019 which has
  144. Xbeen registered with Sun.  Add the following lines to /etc/rpc or your
  145. XYP or Hesiod master:
  146. X
  147. X# Automount control protocol
  148. Xamd    300019    amq
  149. X
  150. X7.  ``Hanging your machine...''
  151. X
  152. XWARNING:  THIS MAY HANG YOUR MACHINE IF YOU GET IT WRONG.
  153. X
  154. XRunning Amd with a carelessly thought out mount map can cause your Amd to
  155. Xenter a deadlock inside the kernel.  For example, attempting to automount a
  156. Xdirectory which is automounted can cause the automounter to issue a mount
  157. Xrequest which will cause the kernel to send an NFS request back to the same
  158. Xautomounter, which is currently stuck in a system call and unable to respond
  159. X- even kill -KILL won't get you out of this one.
  160. X
  161. XThere is nothing you can do to fix it without rebooting your machine, so...
  162. X
  163. XFind a diskless workstation and play with that first before trying this on
  164. Xyour main 200 user service machine (unless you hate your users).  Something
  165. Xlike a diskless Sun-4 is best for development testing - you can compile on a
  166. XSun-4 server and run the binary on the diskless node.  They reboot very fast
  167. Xas well between tests.
  168. X
  169. XNow you can try running Amd.  Please read the documentation in doc/Amd.tex
  170. Xfor more details.  The configuration file "a_master" provides a sample for
  171. Xyou to play with.  Something like:
  172. X
  173. X    ./Amd -c 40 -D test,nodaemon /tmp/amnt a_master &
  174. X
  175. Xis good for testing.  Note that Amd will clean up correctly if you send it a
  176. XSIGINT or SIGTERM.  Other signals are either ignored or will blow it away,
  177. Xleaving your machine in a potentially dangerous state - usually a reboot is
  178. Xall that is required to fix it though ;-)
  179. X
  180. XRemember that Amd needs to run as root in order to do mounts/unmounts though
  181. Xit does check this condition somewhere near line one of main().  It will also
  182. Xneed write permission in the working directory if you have built it with
  183. XDEBUG defined.  Watch out for NFS stepping in and mapping root to nobody.
  184. X
  185. X8.  ``Report what happened...''
  186. X
  187. XIf anything interesting happened, eg it didn't work, please report it to me
  188. X-- Jan-Simon Pendry <jsp@doc.ic.ac.uk> -- as detailed in the README file.
  189. X
  190. XKNOWN PROBLEMS - Contact me for more details
  191. X
  192. X* Amd does not work correctly on a DecStation 3100 system running Ultrix 3.1.
  193. X  This is a bug in Ultrix.  Quite how the Ultrix mount command works is a
  194. X  total mystery, but in any case the mount system call does not behave as
  195. X  documented.
  196. X
  197. X* It is reported that amd deadlocks the kernel on a Sequent Symmetry.
  198. X  Obviously this is a kernel bug.
  199. X
  200. X* Amd cannot do hierarchical mounts, ie mount two or more filesystems at
  201. X  once. To do this requires resolving some non-trivial issues.  If you think
  202. X  you know what the semantics should be I would like to hear from you.
  203. X  Remember to consider the general case.  The tree of mounts can be composed
  204. X  of any combination of filesystem types, and/or possibly come from several
  205. X  NFS servers any of which may be down at the time of the mount.
  206. X
  207. X  Once the tree is mounted, how does it get unmounted?  Again, what happens
  208. X  if a fileserver is down, or goes down after one of the other filesystems is
  209. X  unmounted?
  210. X
  211. X$Id: INSTALL,v 5.1.1.2 90/01/11 16:45:44 jsp Exp Locker: jsp $
  212. END_OF_FILE
  213. if test 7869 -ne `wc -c <'INSTALL'`; then
  214.     echo shar: \"'INSTALL'\" unpacked with wrong size!
  215. fi
  216. # end of 'INSTALL'
  217. fi
  218. if test -f 'misc_rpc.c' -a "${1}" != "-c" ; then 
  219.   echo shar: Will not clobber existing file \"'misc_rpc.c'\"
  220. else
  221. echo shar: Extracting \"'misc_rpc.c'\" \(8404 characters\)
  222. sed "s/^X//" >'misc_rpc.c' <<'END_OF_FILE'
  223. X/*
  224. X * $Id: misc_rpc.c,v 5.1.1.1 90/01/11 17:08:49 jsp Exp Locker: jsp $
  225. X *
  226. X * Copyright (c) 1990 Jan-Simon Pendry
  227. X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  228. X * Copyright (c) 1990 The Regents of the University of California.
  229. X * All rights reserved.
  230. X *
  231. X * This code is derived from software contributed to Berkeley by
  232. X * Jan-Simon Pendry at Imperial College, London.
  233. X *
  234. X * Redistribution and use in source and binary forms are permitted
  235. X * provided that the above copyright notice and this paragraph are
  236. X * duplicated in all such forms and that any documentation,
  237. X * advertising materials, and other materials related to such
  238. X * distribution and use acknowledge that the software was developed
  239. X * by Imperial College of Science, Technology and Medicine, London, UK.
  240. X * The names of the College and University may not be used to endorse
  241. X * or promote products derived from this software without specific
  242. X * prior written permission.
  243. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  244. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  245. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  246. X *
  247. X *    %W% (Berkeley) %G%
  248. X */
  249. X
  250. X/*
  251. X * Additions to Sun RPC.
  252. X */
  253. X
  254. X#include "am.h"
  255. X
  256. Xvoid rpc_msg_init P((struct rpc_msg *mp, u_long prog, u_long vers, u_long proc));
  257. Xvoid rpc_msg_init(mp, prog, vers, proc)
  258. Xstruct rpc_msg *mp;
  259. Xunsigned long prog, vers, proc;
  260. X{
  261. X    /*
  262. X     * Initialise the message
  263. X     */
  264. X    bzero((voidp) mp, sizeof(*mp));
  265. X    mp->rm_xid = 0;
  266. X    mp->rm_direction = CALL;
  267. X    mp->rm_call.cb_rpcvers = RPC_MSG_VERSION;
  268. X    mp->rm_call.cb_prog = prog;
  269. X    mp->rm_call.cb_vers = vers;
  270. X    mp->rm_call.cb_proc = proc;
  271. X}
  272. X
  273. X/*
  274. X * Field reply to call to mountd
  275. X */
  276. Xint pickup_rpc_reply P((voidp pkt, int len, voidp where, xdrproc_t where_xdr));
  277. Xint pickup_rpc_reply(pkt, len, where, where_xdr)
  278. Xvoidp pkt;
  279. Xint len;
  280. Xvoidp where;
  281. Xxdrproc_t where_xdr;
  282. X{
  283. X    XDR reply_xdr;
  284. X    int ok;
  285. X    struct rpc_err err;
  286. X    struct rpc_msg reply_msg;
  287. X    int error = 0;
  288. X
  289. X    /*bzero((voidp) &err, sizeof(err));*/
  290. X    bzero((voidp) &reply_msg, sizeof(reply_msg));
  291. X
  292. X    reply_msg.acpted_rply.ar_results.where = (caddr_t) where;
  293. X    reply_msg.acpted_rply.ar_results.proc = where_xdr;
  294. X
  295. X    xdrmem_create(&reply_xdr, pkt, len, XDR_DECODE);
  296. X
  297. X    ok = xdr_replymsg(&reply_xdr, &reply_msg);
  298. X    if (!ok) {
  299. X        error = EIO;
  300. X        goto drop;
  301. X    }
  302. X    _seterr_reply(&reply_msg, &err);
  303. X    if (err.re_status != RPC_SUCCESS) {
  304. X        error = EIO;
  305. X        goto drop;
  306. X    }
  307. X
  308. Xdrop:
  309. X    if (reply_msg.acpted_rply.ar_verf.oa_base) {
  310. X        reply_xdr.x_op = XDR_FREE;
  311. X        (void)xdr_opaque_auth(&reply_xdr,
  312. X            &reply_msg.acpted_rply.ar_verf);
  313. X    }
  314. X    xdr_destroy(&reply_xdr);
  315. X
  316. X    return error;
  317. X}
  318. X
  319. Xint make_rpc_packet P((char *buf, int buflen, unsigned long proc,
  320. X            struct rpc_msg *mp, voidp arg, xdrproc_t arg_xdr, AUTH *auth));
  321. Xint make_rpc_packet(buf, buflen, proc, mp, arg, arg_xdr, auth)
  322. Xchar *buf;
  323. Xint buflen;
  324. Xunsigned long proc;
  325. Xstruct rpc_msg *mp;
  326. Xvoidp arg;
  327. Xxdrproc_t arg_xdr;
  328. XAUTH *auth;
  329. X{
  330. X    XDR msg_xdr;
  331. X    int len;
  332. X
  333. X    xdrmem_create(&msg_xdr, buf, buflen, XDR_ENCODE);
  334. X    /*
  335. X     * Basic protocol header
  336. X     */
  337. X    if (!xdr_callhdr(&msg_xdr, mp))
  338. X        return -EIO;
  339. X    /*
  340. X     * Called procedure number
  341. X     */
  342. X    if (!xdr_enum(&msg_xdr, &proc))
  343. X        return -EIO;
  344. X    /*
  345. X     * Authorization
  346. X     */
  347. X    if (!AUTH_MARSHALL(auth, &msg_xdr))
  348. X        return -EIO;
  349. X    /*
  350. X     * Arguments
  351. X     */
  352. X    if (!(*arg_xdr)(&msg_xdr, arg))
  353. X        return -EIO;
  354. X    /*
  355. X     * Determine length
  356. X     */
  357. X    len = xdr_getpos(&msg_xdr);
  358. X    /*
  359. X     * Throw away xdr
  360. X     */
  361. X    xdr_destroy(&msg_xdr);
  362. X    return len;
  363. X}
  364. X
  365. X
  366. X#ifdef MISC_RPC
  367. X/*
  368. X * Early RPC seems to be missing these..
  369. X * Extracted from the RPC 3.9 sources as indicated
  370. X */
  371. X
  372. X/* @(#)xdr_reference.c    1.1 87/11/04 3.9 RPCSRC */
  373. X/*
  374. X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  375. X * unrestricted use provided that this legend is included on all tape
  376. X * media and as a part of the software program in whole or part.  Users
  377. X * may copy or modify Sun RPC without charge, but are not authorized
  378. X * to license or distribute it to anyone else except as part of a product or
  379. X * program developed by the user.
  380. X * 
  381. X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  382. X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  383. X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  384. X * 
  385. X * Sun RPC is provided with no support and without any obligation on the
  386. X * part of Sun Microsystems, Inc. to assist in its use, correction,
  387. X * modification or enhancement.
  388. X * 
  389. X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  390. X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  391. X * OR ANY PART THEREOF.
  392. X * 
  393. X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  394. X * or profits or other special, indirect and consequential damages, even if
  395. X * Sun has been advised of the possibility of such damages.
  396. X * 
  397. X * Sun Microsystems, Inc.
  398. X * 2550 Garcia Avenue
  399. X * Mountain View, California  94043
  400. X */
  401. X
  402. X
  403. X/*
  404. X * xdr_pointer():
  405. X *
  406. X * XDR a pointer to a possibly recursive data structure. This
  407. X * differs with xdr_reference in that it can serialize/deserialiaze
  408. X * trees correctly.
  409. X *
  410. X *  What's sent is actually a union:
  411. X *
  412. X *  union object_pointer switch (boolean b) {
  413. X *  case TRUE: object_data data;
  414. X *  case FALSE: void nothing;
  415. X *  }
  416. X *
  417. X * > objpp: Pointer to the pointer to the object.
  418. X * > obj_size: size of the object.
  419. X * > xdr_obj: routine to XDR an object.
  420. X *
  421. X */
  422. Xbool_t
  423. Xxdr_pointer(xdrs,objpp,obj_size,xdr_obj)
  424. X    register XDR *xdrs;
  425. X    char **objpp;
  426. X    u_int obj_size;
  427. X    xdrproc_t xdr_obj;
  428. X{
  429. X
  430. X    bool_t more_data;
  431. X
  432. X    more_data = (*objpp != NULL);
  433. X    if (! xdr_bool(xdrs,&more_data)) {
  434. X        return (FALSE);
  435. X    }
  436. X    if (! more_data) {
  437. X        *objpp = NULL;
  438. X        return (TRUE);
  439. X    }
  440. X    return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
  441. X}
  442. X
  443. X/* @(#)clnt_perror.c    1.1 87/11/04 3.9 RPCSRC */
  444. X/*
  445. X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  446. X * unrestricted use provided that this legend is included on all tape
  447. X * media and as a part of the software program in whole or part.  Users
  448. X * may copy or modify Sun RPC without charge, but are not authorized
  449. X * to license or distribute it to anyone else except as part of a product or
  450. X * program developed by the user.
  451. X * 
  452. X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  453. X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  454. X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  455. X * 
  456. X * Sun RPC is provided with no support and without any obligation on the
  457. X * part of Sun Microsystems, Inc. to assist in its use, correction,
  458. X * modification or enhancement.
  459. X * 
  460. X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  461. X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  462. X * OR ANY PART THEREOF.
  463. X * 
  464. X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  465. X * or profits or other special, indirect and consequential damages, even if
  466. X * Sun has been advised of the possibility of such damages.
  467. X * 
  468. X * Sun Microsystems, Inc.
  469. X * 2550 Garcia Avenue
  470. X * Mountain View, California  94043
  471. X */
  472. X
  473. Xstruct rpc_errtab {
  474. X    enum clnt_stat status;
  475. X    char *message;
  476. X};
  477. X
  478. Xstatic struct rpc_errtab  rpc_errlist[] = {
  479. X    { RPC_SUCCESS, 
  480. X        "RPC: Success" }, 
  481. X    { RPC_CANTENCODEARGS, 
  482. X        "RPC: Can't encode arguments" },
  483. X    { RPC_CANTDECODERES, 
  484. X        "RPC: Can't decode result" },
  485. X    { RPC_CANTSEND, 
  486. X        "RPC: Unable to send" },
  487. X    { RPC_CANTRECV, 
  488. X        "RPC: Unable to receive" },
  489. X    { RPC_TIMEDOUT, 
  490. X        "RPC: Timed out" },
  491. X    { RPC_VERSMISMATCH, 
  492. X        "RPC: Incompatible versions of RPC" },
  493. X    { RPC_AUTHERROR, 
  494. X        "RPC: Authentication error" },
  495. X    { RPC_PROGUNAVAIL, 
  496. X        "RPC: Program unavailable" },
  497. X    { RPC_PROGVERSMISMATCH, 
  498. X        "RPC: Program/version mismatch" },
  499. X    { RPC_PROCUNAVAIL, 
  500. X        "RPC: Procedure unavailable" },
  501. X    { RPC_CANTDECODEARGS, 
  502. X        "RPC: Server can't decode arguments" },
  503. X    { RPC_SYSTEMERROR, 
  504. X        "RPC: Remote system error" },
  505. X    { RPC_UNKNOWNHOST, 
  506. X        "RPC: Unknown host" },
  507. X/*    { RPC_UNKNOWNPROTO,
  508. X        "RPC: Unknown protocol" },*/
  509. X    { RPC_PMAPFAILURE, 
  510. X        "RPC: Port mapper failure" },
  511. X    { RPC_PROGNOTREGISTERED, 
  512. X        "RPC: Program not registered"},
  513. X    { RPC_FAILED, 
  514. X        "RPC: Failed (unspecified error)"}
  515. X};
  516. X
  517. X
  518. X/*
  519. X * This interface for use by clntrpc
  520. X */
  521. Xchar *
  522. Xclnt_sperrno(stat)
  523. X    enum clnt_stat stat;
  524. X{
  525. X    int i;
  526. X
  527. X    for (i = 0; i < sizeof(rpc_errlist)/sizeof(struct rpc_errtab); i++) {
  528. X        if (rpc_errlist[i].status == stat) {
  529. X            return (rpc_errlist[i].message);
  530. X        }
  531. X    }
  532. X    return ("RPC: (unknown error code)");
  533. X}
  534. X
  535. X#endif /* MISC_RPC */
  536. X
  537. END_OF_FILE
  538. if test 8404 -ne `wc -c <'misc_rpc.c'`; then
  539.     echo shar: \"'misc_rpc.c'\" unpacked with wrong size!
  540. fi
  541. # end of 'misc_rpc.c'
  542. fi
  543. if test -f 'nfs_prot_xdr.c' -a "${1}" != "-c" ; then 
  544.   echo shar: Will not clobber existing file \"'nfs_prot_xdr.c'\"
  545. else
  546. echo shar: Extracting \"'nfs_prot_xdr.c'\" \(9341 characters\)
  547. sed "s/^X//" >'nfs_prot_xdr.c' <<'END_OF_FILE'
  548. X/*
  549. X * $Id: nfs_prot_xdr.c,v 5.1 89/11/17 18:21:28 jsp Exp Locker: jsp $
  550. X *
  551. X * Copyright (c) 1989 Jan-Simon Pendry
  552. X * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  553. X * Copyright (c) 1989 The Regents of the University of California.
  554. X * All rights reserved.
  555. X *
  556. X * This code is derived from software contributed to Berkeley by
  557. X * Jan-Simon Pendry at Imperial College, London.
  558. X *
  559. X * Redistribution and use in source and binary forms are permitted
  560. X * provided that the above copyright notice and this paragraph are
  561. X * duplicated in all such forms and that any documentation,
  562. X * advertising materials, and other materials related to such
  563. X * distribution and use acknowledge that the software was developed
  564. X * by Imperial College of Science, Technology and Medicine, London, UK.
  565. X * The names of the College and University may not be used to endorse
  566. X * or promote products derived from this software without specific
  567. X * prior written permission.
  568. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  569. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  570. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  571. X *
  572. X *    %W% (Berkeley) %G%
  573. X */
  574. X
  575. X#include "am.h"
  576. X
  577. X
  578. X#ifndef xdr_nfsstat
  579. Xbool_t
  580. Xxdr_nfsstat(xdrs, objp)
  581. X    XDR *xdrs;
  582. X    nfsstat *objp;
  583. X{
  584. X    if (!xdr_enum(xdrs, (enum_t *)objp)) {
  585. X        return (FALSE);
  586. X    }
  587. X    return (TRUE);
  588. X}
  589. X#endif
  590. X
  591. X
  592. X
  593. X#ifndef xdr_ftype
  594. Xstatic bool_t
  595. Xxdr_ftype(xdrs, objp)
  596. X    XDR *xdrs;
  597. X    ftype *objp;
  598. X{
  599. X    if (!xdr_enum(xdrs, (enum_t *)objp)) {
  600. X        return (FALSE);
  601. X    }
  602. X    return (TRUE);
  603. X}
  604. X#endif
  605. X
  606. X
  607. X
  608. Xbool_t
  609. Xxdr_nfs_fh(xdrs, objp)
  610. X    XDR *xdrs;
  611. X    nfs_fh *objp;
  612. X{
  613. X    if (!xdr_opaque(xdrs, objp->data, NFS_FHSIZE)) {
  614. X        return (FALSE);
  615. X    }
  616. X    return (TRUE);
  617. X}
  618. X
  619. X
  620. X
  621. X
  622. Xstatic bool_t
  623. Xxdr_nfstime(xdrs, objp)
  624. X    XDR *xdrs;
  625. X    nfstime *objp;
  626. X{
  627. X    if (!xdr_u_int(xdrs, &objp->seconds)) {
  628. X        return (FALSE);
  629. X    }
  630. X    if (!xdr_u_int(xdrs, &objp->useconds)) {
  631. X        return (FALSE);
  632. X    }
  633. X    return (TRUE);
  634. X}
  635. X
  636. X
  637. X
  638. X
  639. Xstatic bool_t
  640. Xxdr_fattr(xdrs, objp)
  641. X    XDR *xdrs;
  642. X    fattr *objp;
  643. X{
  644. X    if (!xdr_ftype(xdrs, &objp->type)) {
  645. X        return (FALSE);
  646. X    }
  647. X    if (!xdr_u_int(xdrs, &objp->mode)) {
  648. X        return (FALSE);
  649. X    }
  650. X    if (!xdr_u_int(xdrs, &objp->nlink)) {
  651. X        return (FALSE);
  652. X    }
  653. X    if (!xdr_u_int(xdrs, &objp->uid)) {
  654. X        return (FALSE);
  655. X    }
  656. X    if (!xdr_u_int(xdrs, &objp->gid)) {
  657. X        return (FALSE);
  658. X    }
  659. X    if (!xdr_u_int(xdrs, &objp->size)) {
  660. X        return (FALSE);
  661. X    }
  662. X    if (!xdr_u_int(xdrs, &objp->blocksize)) {
  663. X        return (FALSE);
  664. X    }
  665. X    if (!xdr_u_int(xdrs, &objp->rdev)) {
  666. X        return (FALSE);
  667. X    }
  668. X    if (!xdr_u_int(xdrs, &objp->blocks)) {
  669. X        return (FALSE);
  670. X    }
  671. X    if (!xdr_u_int(xdrs, &objp->fsid)) {
  672. X        return (FALSE);
  673. X    }
  674. X    if (!xdr_u_int(xdrs, &objp->fileid)) {
  675. X        return (FALSE);
  676. X    }
  677. X    if (!xdr_nfstime(xdrs, &objp->atime)) {
  678. X        return (FALSE);
  679. X    }
  680. X    if (!xdr_nfstime(xdrs, &objp->mtime)) {
  681. X        return (FALSE);
  682. X    }
  683. X    if (!xdr_nfstime(xdrs, &objp->ctime)) {
  684. X        return (FALSE);
  685. X    }
  686. X    return (TRUE);
  687. X}
  688. X
  689. X
  690. X
  691. X
  692. Xstatic bool_t
  693. Xxdr_sattr(xdrs, objp)
  694. X    XDR *xdrs;
  695. X    sattr *objp;
  696. X{
  697. X    if (!xdr_u_int(xdrs, &objp->mode)) {
  698. X        return (FALSE);
  699. X    }
  700. X    if (!xdr_u_int(xdrs, &objp->uid)) {
  701. X        return (FALSE);
  702. X    }
  703. X    if (!xdr_u_int(xdrs, &objp->gid)) {
  704. X        return (FALSE);
  705. X    }
  706. X    if (!xdr_u_int(xdrs, &objp->size)) {
  707. X        return (FALSE);
  708. X    }
  709. X    if (!xdr_nfstime(xdrs, &objp->atime)) {
  710. X        return (FALSE);
  711. X    }
  712. X    if (!xdr_nfstime(xdrs, &objp->mtime)) {
  713. X        return (FALSE);
  714. X    }
  715. X    return (TRUE);
  716. X}
  717. X
  718. X
  719. X
  720. X
  721. Xstatic bool_t
  722. Xxdr_filename(xdrs, objp)
  723. X    XDR *xdrs;
  724. X    filename *objp;
  725. X{
  726. X    if (!xdr_string(xdrs, objp, NFS_MAXNAMLEN)) {
  727. X        return (FALSE);
  728. X    }
  729. X    return (TRUE);
  730. X}
  731. X
  732. X
  733. X
  734. X
  735. Xbool_t
  736. Xxdr_nfspath(xdrs, objp)
  737. X    XDR *xdrs;
  738. X    nfspath *objp;
  739. X{
  740. X    if (!xdr_string(xdrs, objp, NFS_MAXPATHLEN)) {
  741. X        return (FALSE);
  742. X    }
  743. X    return (TRUE);
  744. X}
  745. X
  746. X
  747. X
  748. X
  749. Xbool_t
  750. Xxdr_attrstat(xdrs, objp)
  751. X    XDR *xdrs;
  752. X    attrstat *objp;
  753. X{
  754. X    if (!xdr_nfsstat(xdrs, &objp->status)) {
  755. X        return (FALSE);
  756. X    }
  757. X    switch (objp->status) {
  758. X    case NFS_OK:
  759. X        if (!xdr_fattr(xdrs, &objp->attrstat_u.attributes)) {
  760. X            return (FALSE);
  761. X        }
  762. X        break;
  763. X    }
  764. X    return (TRUE);
  765. X}
  766. X
  767. X
  768. X
  769. X
  770. Xbool_t
  771. Xxdr_sattrargs(xdrs, objp)
  772. X    XDR *xdrs;
  773. X    sattrargs *objp;
  774. X{
  775. X    if (!xdr_nfs_fh(xdrs, &objp->file)) {
  776. X        return (FALSE);
  777. X    }
  778. X    if (!xdr_sattr(xdrs, &objp->attributes)) {
  779. X        return (FALSE);
  780. X    }
  781. X    return (TRUE);
  782. X}
  783. X
  784. X
  785. X
  786. X
  787. Xbool_t
  788. Xxdr_diropargs(xdrs, objp)
  789. X    XDR *xdrs;
  790. X    diropargs *objp;
  791. X{
  792. X    if (!xdr_nfs_fh(xdrs, &objp->dir)) {
  793. X        return (FALSE);
  794. X    }
  795. X    if (!xdr_filename(xdrs, &objp->name)) {
  796. X        return (FALSE);
  797. X    }
  798. X    return (TRUE);
  799. X}
  800. X
  801. X
  802. X
  803. X
  804. Xbool_t
  805. Xxdr_diropokres(xdrs, objp)
  806. X    XDR *xdrs;
  807. X    diropokres *objp;
  808. X{
  809. X    if (!xdr_nfs_fh(xdrs, &objp->file)) {
  810. X        return (FALSE);
  811. X    }
  812. X    if (!xdr_fattr(xdrs, &objp->attributes)) {
  813. X        return (FALSE);
  814. X    }
  815. X    return (TRUE);
  816. X}
  817. X
  818. X
  819. X
  820. X
  821. Xbool_t
  822. Xxdr_diropres(xdrs, objp)
  823. X    XDR *xdrs;
  824. X    diropres *objp;
  825. X{
  826. X    if (!xdr_nfsstat(xdrs, &objp->status)) {
  827. X        return (FALSE);
  828. X    }
  829. X    switch (objp->status) {
  830. X    case NFS_OK:
  831. X        if (!xdr_diropokres(xdrs, &objp->diropres_u.diropres)) {
  832. X            return (FALSE);
  833. X        }
  834. X        break;
  835. X    }
  836. X    return (TRUE);
  837. X}
  838. X
  839. X
  840. X
  841. X
  842. Xbool_t
  843. Xxdr_readlinkres(xdrs, objp)
  844. X    XDR *xdrs;
  845. X    readlinkres *objp;
  846. X{
  847. X    if (!xdr_nfsstat(xdrs, &objp->status)) {
  848. X        return (FALSE);
  849. X    }
  850. X    switch (objp->status) {
  851. X    case NFS_OK:
  852. X        if (!xdr_nfspath(xdrs, &objp->readlinkres_u.data)) {
  853. X            return (FALSE);
  854. X        }
  855. X        break;
  856. X    }
  857. X    return (TRUE);
  858. X}
  859. X
  860. X
  861. X
  862. X
  863. Xbool_t
  864. Xxdr_readargs(xdrs, objp)
  865. X    XDR *xdrs;
  866. X    readargs *objp;
  867. X{
  868. X    if (!xdr_nfs_fh(xdrs, &objp->file)) {
  869. X        return (FALSE);
  870. X    }
  871. X    if (!xdr_u_int(xdrs, &objp->offset)) {
  872. X        return (FALSE);
  873. X    }
  874. X    if (!xdr_u_int(xdrs, &objp->count)) {
  875. X        return (FALSE);
  876. X    }
  877. X    if (!xdr_u_int(xdrs, &objp->totalcount)) {
  878. X        return (FALSE);
  879. X    }
  880. X    return (TRUE);
  881. X}
  882. X
  883. X
  884. X
  885. X
  886. Xbool_t
  887. Xxdr_readokres(xdrs, objp)
  888. X    XDR *xdrs;
  889. X    readokres *objp;
  890. X{
  891. X    if (!xdr_fattr(xdrs, &objp->attributes)) {
  892. X        return (FALSE);
  893. X    }
  894. X    if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
  895. X        return (FALSE);
  896. X    }
  897. X    return (TRUE);
  898. X}
  899. X
  900. X
  901. X
  902. X
  903. Xbool_t
  904. Xxdr_readres(xdrs, objp)
  905. X    XDR *xdrs;
  906. X    readres *objp;
  907. X{
  908. X    if (!xdr_nfsstat(xdrs, &objp->status)) {
  909. X        return (FALSE);
  910. X    }
  911. X    switch (objp->status) {
  912. X    case NFS_OK:
  913. X        if (!xdr_readokres(xdrs, &objp->readres_u.reply)) {
  914. X            return (FALSE);
  915. X        }
  916. X        break;
  917. X    }
  918. X    return (TRUE);
  919. X}
  920. X
  921. X
  922. X
  923. X
  924. Xbool_t
  925. Xxdr_writeargs(xdrs, objp)
  926. X    XDR *xdrs;
  927. X    writeargs *objp;
  928. X{
  929. X    if (!xdr_nfs_fh(xdrs, &objp->file)) {
  930. X        return (FALSE);
  931. X    }
  932. X    if (!xdr_u_int(xdrs, &objp->beginoffset)) {
  933. X        return (FALSE);
  934. X    }
  935. X    if (!xdr_u_int(xdrs, &objp->offset)) {
  936. X        return (FALSE);
  937. X    }
  938. X    if (!xdr_u_int(xdrs, &objp->totalcount)) {
  939. X        return (FALSE);
  940. X    }
  941. X    if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
  942. X        return (FALSE);
  943. X    }
  944. X    return (TRUE);
  945. X}
  946. X
  947. X
  948. X
  949. X
  950. Xbool_t
  951. Xxdr_createargs(xdrs, objp)
  952. X    XDR *xdrs;
  953. X    createargs *objp;
  954. X{
  955. X    if (!xdr_diropargs(xdrs, &objp->where)) {
  956. X        return (FALSE);
  957. X    }
  958. X    if (!xdr_sattr(xdrs, &objp->attributes)) {
  959. X        return (FALSE);
  960. X    }
  961. X    return (TRUE);
  962. X}
  963. X
  964. X
  965. X
  966. X
  967. Xbool_t
  968. Xxdr_renameargs(xdrs, objp)
  969. X    XDR *xdrs;
  970. X    renameargs *objp;
  971. X{
  972. X    if (!xdr_diropargs(xdrs, &objp->from)) {
  973. X        return (FALSE);
  974. X    }
  975. X    if (!xdr_diropargs(xdrs, &objp->to)) {
  976. X        return (FALSE);
  977. X    }
  978. X    return (TRUE);
  979. X}
  980. X
  981. X
  982. X
  983. X
  984. Xbool_t
  985. Xxdr_linkargs(xdrs, objp)
  986. X    XDR *xdrs;
  987. X    linkargs *objp;
  988. X{
  989. X    if (!xdr_nfs_fh(xdrs, &objp->from)) {
  990. X        return (FALSE);
  991. X    }
  992. X    if (!xdr_diropargs(xdrs, &objp->to)) {
  993. X        return (FALSE);
  994. X    }
  995. X    return (TRUE);
  996. X}
  997. X
  998. X
  999. X
  1000. X
  1001. Xbool_t
  1002. Xxdr_symlinkargs(xdrs, objp)
  1003. X    XDR *xdrs;
  1004. X    symlinkargs *objp;
  1005. X{
  1006. X    if (!xdr_diropargs(xdrs, &objp->from)) {
  1007. X        return (FALSE);
  1008. X    }
  1009. X    if (!xdr_nfspath(xdrs, &objp->to)) {
  1010. X        return (FALSE);
  1011. X    }
  1012. X    if (!xdr_sattr(xdrs, &objp->attributes)) {
  1013. X        return (FALSE);
  1014. X    }
  1015. X    return (TRUE);
  1016. X}
  1017. X
  1018. X
  1019. X
  1020. X
  1021. Xstatic bool_t
  1022. Xxdr_nfscookie(xdrs, objp)
  1023. X    XDR *xdrs;
  1024. X    nfscookie objp;
  1025. X{
  1026. X    if (!xdr_opaque(xdrs, objp, NFS_COOKIESIZE)) {
  1027. X        return (FALSE);
  1028. X    }
  1029. X    return (TRUE);
  1030. X}
  1031. X
  1032. X
  1033. X
  1034. X
  1035. Xbool_t
  1036. Xxdr_readdirargs(xdrs, objp)
  1037. X    XDR *xdrs;
  1038. X    readdirargs *objp;
  1039. X{
  1040. X    if (!xdr_nfs_fh(xdrs, &objp->dir)) {
  1041. X        return (FALSE);
  1042. X    }
  1043. X    if (!xdr_nfscookie(xdrs, objp->cookie)) {
  1044. X        return (FALSE);
  1045. X    }
  1046. X    if (!xdr_u_int(xdrs, &objp->count)) {
  1047. X        return (FALSE);
  1048. X    }
  1049. X    return (TRUE);
  1050. X}
  1051. X
  1052. X
  1053. X
  1054. X
  1055. Xstatic bool_t
  1056. Xxdr_entry(xdrs, objp)
  1057. X    XDR *xdrs;
  1058. X    entry *objp;
  1059. X{
  1060. X    if (!xdr_u_int(xdrs, &objp->fileid)) {
  1061. X        return (FALSE);
  1062. X    }
  1063. X    if (!xdr_filename(xdrs, &objp->name)) {
  1064. X        return (FALSE);
  1065. X    }
  1066. X    if (!xdr_nfscookie(xdrs, objp->cookie)) {
  1067. X        return (FALSE);
  1068. X    }
  1069. X    if (!xdr_pointer(xdrs, (char **)&objp->nextentry, sizeof(entry), xdr_entry)) {
  1070. X        return (FALSE);
  1071. X    }
  1072. X    return (TRUE);
  1073. X}
  1074. X
  1075. X
  1076. X
  1077. X
  1078. Xstatic bool_t
  1079. Xxdr_dirlist(xdrs, objp)
  1080. X    XDR *xdrs;
  1081. X    dirlist *objp;
  1082. X{
  1083. X    if (!xdr_pointer(xdrs, (char **)&objp->entries, sizeof(entry), xdr_entry)) {
  1084. X        return (FALSE);
  1085. X    }
  1086. X    if (!xdr_bool(xdrs, &objp->eof)) {
  1087. X        return (FALSE);
  1088. X    }
  1089. X    return (TRUE);
  1090. X}
  1091. X
  1092. X
  1093. X
  1094. X
  1095. Xbool_t
  1096. Xxdr_readdirres(xdrs, objp)
  1097. X    XDR *xdrs;
  1098. X    readdirres *objp;
  1099. X{
  1100. X    if (!xdr_nfsstat(xdrs, &objp->status)) {
  1101. X        return (FALSE);
  1102. X    }
  1103. X    switch (objp->status) {
  1104. X    case NFS_OK:
  1105. X        if (!xdr_dirlist(xdrs, &objp->readdirres_u.reply)) {
  1106. X            return (FALSE);
  1107. X        }
  1108. X        break;
  1109. X    }
  1110. X    return (TRUE);
  1111. X}
  1112. X
  1113. X
  1114. X
  1115. X
  1116. Xbool_t
  1117. Xxdr_statfsokres(xdrs, objp)
  1118. X    XDR *xdrs;
  1119. X    statfsokres *objp;
  1120. X{
  1121. X    if (!xdr_u_int(xdrs, &objp->tsize)) {
  1122. X        return (FALSE);
  1123. X    }
  1124. X    if (!xdr_u_int(xdrs, &objp->bsize)) {
  1125. X        return (FALSE);
  1126. X    }
  1127. X    if (!xdr_u_int(xdrs, &objp->blocks)) {
  1128. X        return (FALSE);
  1129. X    }
  1130. X    if (!xdr_u_int(xdrs, &objp->bfree)) {
  1131. X        return (FALSE);
  1132. X    }
  1133. X    if (!xdr_u_int(xdrs, &objp->bavail)) {
  1134. X        return (FALSE);
  1135. X    }
  1136. X    return (TRUE);
  1137. X}
  1138. X
  1139. X
  1140. X
  1141. X
  1142. Xbool_t
  1143. Xxdr_statfsres(xdrs, objp)
  1144. X    XDR *xdrs;
  1145. X    statfsres *objp;
  1146. X{
  1147. X    if (!xdr_nfsstat(xdrs, &objp->status)) {
  1148. X        return (FALSE);
  1149. X    }
  1150. X    switch (objp->status) {
  1151. X    case NFS_OK:
  1152. X        if (!xdr_statfsokres(xdrs, &objp->statfsres_u.reply)) {
  1153. X            return (FALSE);
  1154. X        }
  1155. X        break;
  1156. X    }
  1157. X    return (TRUE);
  1158. X}
  1159. END_OF_FILE
  1160. if test 9341 -ne `wc -c <'nfs_prot_xdr.c'`; then
  1161.     echo shar: \"'nfs_prot_xdr.c'\" unpacked with wrong size!
  1162. fi
  1163. # end of 'nfs_prot_xdr.c'
  1164. fi
  1165. if test -f 'nfs_start.c' -a "${1}" != "-c" ; then 
  1166.   echo shar: Will not clobber existing file \"'nfs_start.c'\"
  1167. else
  1168. echo shar: Extracting \"'nfs_start.c'\" \(7449 characters\)
  1169. sed "s/^X//" >'nfs_start.c' <<'END_OF_FILE'
  1170. X/*
  1171. X * $Id: nfs_start.c,v 5.1.1.2 90/01/11 17:13:06 jsp Exp Locker: jsp $
  1172. X *
  1173. X * Copyright (c) 1990 Jan-Simon Pendry
  1174. X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  1175. X * Copyright (c) 1990 The Regents of the University of California.
  1176. X * All rights reserved.
  1177. X *
  1178. X * This code is derived from software contributed to Berkeley by
  1179. X * Jan-Simon Pendry at Imperial College, London.
  1180. X *
  1181. X * Redistribution and use in source and binary forms are permitted
  1182. X * provided that the above copyright notice and this paragraph are
  1183. X * duplicated in all such forms and that any documentation,
  1184. X * advertising materials, and other materials related to such
  1185. X * distribution and use acknowledge that the software was developed
  1186. X * by Imperial College of Science, Technology and Medicine, London, UK.
  1187. X * The names of the College and University may not be used to endorse
  1188. X * or promote products derived from this software without specific
  1189. X * prior written permission.
  1190. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1191. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1192. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1193. X *
  1194. X *    %W% (Berkeley) %G%
  1195. X */
  1196. X
  1197. X#include "am.h"
  1198. X#include "amq.h"
  1199. X#include <sys/signal.h>
  1200. X#include <setjmp.h>
  1201. Xextern jmp_buf select_intr;
  1202. Xextern int select_intr_valid;
  1203. X
  1204. X#ifdef HAS_TFS
  1205. X/*
  1206. X * Use replacement for RPC/UDP transport
  1207. X * so that we do NFS gatewaying.
  1208. X */
  1209. X#define    svcudp_create svcudp2_create
  1210. Xextern SVCXPRT *svcudp2_create P((int));
  1211. X#endif
  1212. X
  1213. Xextern void nfs_program_2();
  1214. Xextern void amq_program_1();
  1215. X
  1216. Xunsigned short nfs_port;
  1217. XSVCXPRT *nfsxprt;
  1218. X
  1219. Xextern int fwd_sock;
  1220. X
  1221. X#ifndef NFDS
  1222. Xstatic int nfds = -1;
  1223. X#ifdef FD_SET
  1224. X#define    NFDS (nfds < 0 ? nfds = getdtablesize() : nfds)
  1225. X#else
  1226. X#define NFDS (sizeof(int) * 8)
  1227. X#endif
  1228. X#endif
  1229. X
  1230. X#define    MASKED_SIGS    (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
  1231. X
  1232. X#ifdef DEBUG
  1233. X/*
  1234. X * Check that we are not burning resources
  1235. X */
  1236. Xstatic void checkup(P_void)
  1237. X{
  1238. X
  1239. Xstatic int max_fd = 0;
  1240. Xstatic char *max_mem = 0;
  1241. X
  1242. X    int next_fd = dup(0);
  1243. X    extern caddr_t sbrk P((int));
  1244. X    caddr_t next_mem = sbrk(0);
  1245. X    close(next_fd);
  1246. X
  1247. X    /*if (max_fd < 0) {
  1248. X        max_fd = next_fd;
  1249. X    } else*/ if (max_fd < next_fd) {
  1250. X        dlog("%d new fds allocated; total is %d",
  1251. X            next_fd - max_fd, next_fd);
  1252. X        max_fd = next_fd;
  1253. X    }
  1254. X
  1255. X    /*if (max_mem == 0) {
  1256. X        max_mem = next_mem;
  1257. X    } else*/ if (max_mem < next_mem) {
  1258. X        dlog("%#x bytes of memory allocated; total is %#x (%d pages)",
  1259. X            next_mem - max_mem,
  1260. X            next_mem,
  1261. X            ((int)next_mem+getpagesize()-1)/getpagesize());
  1262. X        max_mem = next_mem;
  1263. X    }
  1264. X}
  1265. X#endif
  1266. X
  1267. Xstatic int do_select(smask, fds, fdp, tvp)
  1268. Xint smask;
  1269. Xint fds;
  1270. Xint *fdp;
  1271. Xstruct timeval *tvp;
  1272. X{
  1273. X    int sig;
  1274. X    int nsel;
  1275. X    if (sig = setjmp(select_intr)) {
  1276. X        select_intr_valid = 0;
  1277. X        /* Got a signal */
  1278. X        switch (sig) {
  1279. X        case SIGINT:
  1280. X        case SIGTERM:
  1281. X            amd_state = Finishing;
  1282. X            reschedule_timeout_mp();
  1283. X            break;
  1284. X        }
  1285. X        nsel = -1;
  1286. X        errno = EINTR;
  1287. X    } else {
  1288. X        select_intr_valid = 1;
  1289. X        /*
  1290. X         * Invalidate the current clock value
  1291. X         */
  1292. X        clock_valid = 0;
  1293. X        /*
  1294. X         * Allow interrupts.  If a signal
  1295. X         * occurs, then it will cause a longjmp
  1296. X         * up above.
  1297. X         */
  1298. X        (void) sigsetmask(smask);
  1299. X        /*
  1300. X         * Wait for input
  1301. X         */
  1302. X        nsel = select(fds, fdp, (int *) 0, (int *) 0,
  1303. X                tvp->tv_sec ? tvp : (struct timeval *) 0);
  1304. X
  1305. X    }
  1306. X
  1307. X    (void) sigblock(MASKED_SIGS);
  1308. X
  1309. X    /*
  1310. X     * Perhaps reload the cache?
  1311. X     */
  1312. X    if (do_mapc_reload < clocktime()) {
  1313. X        mapc_reload();
  1314. X        do_mapc_reload = clocktime() + ONE_HOUR;
  1315. X    }
  1316. X    return nsel;
  1317. X}
  1318. X
  1319. Xstatic serv_state run_rpc(P_void)
  1320. X{
  1321. X    int dtbsz = NFDS;
  1322. X    int smask = sigblock(MASKED_SIGS);
  1323. X
  1324. X    next_softclock = clocktime();
  1325. X
  1326. X    amd_state = Run;
  1327. X
  1328. X    /*
  1329. X     * Keep on trucking while we are in Run mode.  This state
  1330. X     * is switched to Quit after all the file systems have
  1331. X     * been unmounted.
  1332. X     */
  1333. X    while ((int)amd_state <= (int)Finishing) {
  1334. X        struct timeval tvv;
  1335. X        int nsel;
  1336. X        time_t now;
  1337. X#ifdef RPC_4
  1338. X        fd_set readfds;
  1339. X        readfds = svc_fdset;
  1340. X        FD_SET(fwd_sock, &readfds);
  1341. X#else
  1342. X#ifdef FD_SET
  1343. X        fd_set readfds;
  1344. X        FD_ZERO(&readfds);
  1345. X        readfds.fds_bits[0] = svc_fds;
  1346. X        FD_SET(fwd_sock, &readfds);
  1347. X#else
  1348. X        int readfds = svc_fds | (1 << fwd_sock);
  1349. X#endif /* FD_SET */
  1350. X#endif /* RPC_4 */
  1351. X
  1352. X#ifdef DEBUG
  1353. X        checkup();
  1354. X#endif
  1355. X
  1356. X        /*
  1357. X         * If the full timeout code is not called,
  1358. X         * then recompute the time delta manually.
  1359. X         */
  1360. X        now = clocktime();
  1361. X
  1362. X        if (next_softclock <= now) {
  1363. X            if (amd_state == Finishing)
  1364. X                umount_exported();
  1365. X            tvv.tv_sec = softclock();
  1366. X        } else {
  1367. X            tvv.tv_sec = next_softclock - now;
  1368. X        }
  1369. X        tvv.tv_usec = 0;
  1370. X
  1371. X        if (amd_state == Finishing && last_used_map < 0) {
  1372. X            flush_mntfs();
  1373. X            amd_state = Quit;
  1374. X            break;
  1375. X        }
  1376. X
  1377. X#ifdef DEBUG
  1378. X        if (tvv.tv_sec)
  1379. X            dlog("Select waits for %ds", tvv.tv_sec);
  1380. X        else
  1381. X            dlog("Select waits for Godot");
  1382. X#endif
  1383. X
  1384. X        nsel = do_select(smask, dtbsz, &readfds, &tvv);
  1385. X
  1386. X
  1387. X        switch (nsel) {
  1388. X        case -1:
  1389. X            if (errno == EINTR) {
  1390. X#ifdef DEBUG
  1391. X                dlog("select interrupted");
  1392. X#endif
  1393. X                continue;
  1394. X            }
  1395. X            perror("select");
  1396. X            break;
  1397. X
  1398. X        case 0:
  1399. X#ifdef DEBUG
  1400. X            /*dlog("select returned 0");*/
  1401. X#endif
  1402. X            break;
  1403. X
  1404. X        default:
  1405. X#ifdef FD_SET
  1406. X            if (FD_ISSET(fwd_sock, &readfds)) {
  1407. X                FD_CLR(fwd_sock, &readfds);
  1408. X                fwd_reply();
  1409. X                --nsel;
  1410. X            }
  1411. X#else
  1412. X            if (readfds & (1 << fwd_sock)) {
  1413. X                readfds &= ~(1 << fwd_sock);
  1414. X                fwd_reply();
  1415. X                --nsel;
  1416. X            }
  1417. X#endif
  1418. X
  1419. X            if (nsel) {
  1420. X                /*
  1421. X                 * Anything left must be a normal
  1422. X                 * RPC request.
  1423. X                 */
  1424. X#ifdef RPC_4
  1425. X                svc_getreqset(&readfds);
  1426. X#else
  1427. X#ifdef FD_SET
  1428. X                svc_getreq(readfds.fds_bits[0]);
  1429. X#else
  1430. X                svc_getreq(readfds);
  1431. X#endif
  1432. X#endif
  1433. X            }
  1434. X            break;
  1435. X        }
  1436. X    }
  1437. X
  1438. X    (void) sigsetmask(smask);
  1439. X
  1440. X    if (amd_state == Quit)
  1441. X        amd_state = Done;
  1442. X
  1443. X    return amd_state;
  1444. X}
  1445. X
  1446. Xstatic int bindnfs_port(so)
  1447. Xint so;
  1448. X{
  1449. X    unsigned short port;
  1450. X    int error = bind_resv_port(so, &port);
  1451. X    if (error == 0)
  1452. X        nfs_port = port;
  1453. X    return error;
  1454. X}
  1455. X
  1456. Xvoid unregister_amq(P_void)
  1457. X{
  1458. X#ifdef DEBUG
  1459. X    Debug(D_AMQ)
  1460. X#endif
  1461. X    (void) pmap_unset(AMQ_PROGRAM, AMQ_VERSION);
  1462. X}
  1463. X
  1464. Xint mount_automounter(ppid)
  1465. Xint ppid;
  1466. X{
  1467. X    int so = socket(AF_INET, SOCK_DGRAM, 0);
  1468. X    SVCXPRT *amqp;
  1469. X    int nmount;
  1470. X
  1471. X    unregister_amq();
  1472. X
  1473. X    if (so < 0 || bindnfs_port(so) < 0) {
  1474. X        perror("Can't create privileged nfs port");
  1475. X        return 1;
  1476. X    }
  1477. X
  1478. X    if ((nfsxprt = svcudp_create(so)) == NULL || 
  1479. X            (amqp = svcudp_create(so)) == NULL) {
  1480. X        plog(XLOG_FATAL, "cannot create rpc/udp service");
  1481. X        return 2;
  1482. X    }
  1483. X
  1484. X    if (!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, nfs_program_2, 0)) {
  1485. X        plog(XLOG_FATAL, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)");
  1486. X        return 3;
  1487. X    }
  1488. X
  1489. X#ifdef DEBUG
  1490. X    Debug(D_AMQ)
  1491. X#endif
  1492. X    if (!svc_register(amqp, AMQ_PROGRAM, AMQ_VERSION, amq_program_1, IPPROTO_UDP)) {
  1493. X        plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM, AMQ_VERSION, udp)");
  1494. X        return 3;
  1495. X    }
  1496. X
  1497. X    /*
  1498. X     * Start RPC forwarding
  1499. X     */
  1500. X    if (fwd_init() != 0)
  1501. X        return 3;
  1502. X
  1503. X    /*
  1504. X     * Construct the root automount node
  1505. X     */
  1506. X    make_root_node();
  1507. X
  1508. X    /*
  1509. X     * Pick up the pieces from a previous run
  1510. X     * This is likely to (indirectly) need the rpc_fwd package
  1511. X     * so it *must* come after the call to fwd_init().
  1512. X     */
  1513. X    if (restart_existing_mounts)
  1514. X        restart();
  1515. X
  1516. X    /*
  1517. X     * Mount the top-level auto-mountpoints
  1518. X     */
  1519. X    nmount = mount_exported();
  1520. X
  1521. X    /*
  1522. X     * Now safe to tell parent that we are up and running
  1523. X     */
  1524. X    if (ppid)
  1525. X        kill(ppid, SIGQUIT);
  1526. X
  1527. X    if (nmount == 0) {
  1528. X        plog(XLOG_FATAL, "No work to do - quitting");
  1529. X        amd_state = Done;
  1530. X        return 0;
  1531. X    }
  1532. X
  1533. X    /*
  1534. X     * Start timeout_mp rolling
  1535. X     */
  1536. X    reschedule_timeout_mp();
  1537. X
  1538. X    /*
  1539. X     * Start the server
  1540. X     */
  1541. X    if (run_rpc() != Done) {
  1542. X        plog(XLOG_FATAL, "run_rpc failed");
  1543. X        amd_state = Done;
  1544. X    }
  1545. X
  1546. X    return 0;
  1547. X}
  1548. END_OF_FILE
  1549. if test 7449 -ne `wc -c <'nfs_start.c'`; then
  1550.     echo shar: \"'nfs_start.c'\" unpacked with wrong size!
  1551. fi
  1552. # end of 'nfs_start.c'
  1553. fi
  1554. if test -f 'nfs_stubs.c' -a "${1}" != "-c" ; then 
  1555.   echo shar: Will not clobber existing file \"'nfs_stubs.c'\"
  1556. else
  1557. echo shar: Extracting \"'nfs_stubs.c'\" \(9501 characters\)
  1558. sed "s/^X//" >'nfs_stubs.c' <<'END_OF_FILE'
  1559. X/*
  1560. X * $Id: nfs_stubs.c,v 5.1.1.2 90/01/11 17:14:34 jsp Exp Locker: jsp $
  1561. X *
  1562. X * Copyright (c) 1990 Jan-Simon Pendry
  1563. X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  1564. X * Copyright (c) 1990 The Regents of the University of California.
  1565. X * All rights reserved.
  1566. X *
  1567. X * This code is derived from software contributed to Berkeley by
  1568. X * Jan-Simon Pendry at Imperial College, London.
  1569. X *
  1570. X * Redistribution and use in source and binary forms are permitted
  1571. X * provided that the above copyright notice and this paragraph are
  1572. X * duplicated in all such forms and that any documentation,
  1573. X * advertising materials, and other materials related to such
  1574. X * distribution and use acknowledge that the software was developed
  1575. X * by Imperial College of Science, Technology and Medicine, London, UK.
  1576. X * The names of the College and University may not be used to endorse
  1577. X * or promote products derived from this software without specific
  1578. X * prior written permission.
  1579. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1580. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1581. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1582. X *
  1583. X *    %W% (Berkeley) %G%
  1584. X */
  1585. X
  1586. X#include "am.h"
  1587. X
  1588. X/*
  1589. X * Convert from UN*X to NFS error code
  1590. X */
  1591. X#ifdef NFS_ERROR_MAPPING
  1592. XNFS_ERROR_MAPPING
  1593. X#define nfs_error(e) \
  1594. X        ((nfsstat)((e) > NFS_LOMAP && (e) < NFS_HIMAP ? \
  1595. X        nfs_errormap[(e) - NFS_LOMAP] : (e)))
  1596. X#else
  1597. X#define nfs_error(e) ((nfsstat)(e))
  1598. X#endif
  1599. X
  1600. Xstatic char *do_readlink(mp, error_return)
  1601. Xam_node *mp;
  1602. Xint *error_return;
  1603. X{
  1604. X    /*
  1605. X     * If there is a readlink method, then use
  1606. X     * that, otherwise if a link exists use
  1607. X     * that, otherwise use the mount point.
  1608. X     */
  1609. X    if (mp->am_mnt->mf_ops->readlink) {
  1610. X        int retry = 0;
  1611. X        char *ln = (*mp->am_mnt->mf_ops->readlink)(mp, &retry);
  1612. X        if (ln == 0)
  1613. X            *error_return = retry;
  1614. X        /*reschedule_timeout_mp();*/
  1615. X        return ln;
  1616. X    } else if (mp->am_link) {
  1617. X        return mp->am_link;
  1618. X    } else {
  1619. X        return mp->am_mnt->mf_mount;
  1620. X    }
  1621. X}
  1622. X
  1623. X/*ARGSUSED*/
  1624. Xvoidp 
  1625. Xnfsproc_null_2(argp, rqstp)
  1626. Xvoidp argp;
  1627. Xstruct svc_req *rqstp;
  1628. X{
  1629. X    static char res;
  1630. X
  1631. X    return (voidp) &res;
  1632. X}
  1633. X
  1634. X
  1635. X/*ARGSUSED*/
  1636. Xstruct attrstat *
  1637. Xnfsproc_getattr_2(argp, rqstp)
  1638. Xstruct nfs_fh *argp;
  1639. Xstruct svc_req *rqstp;
  1640. X{
  1641. X    static struct attrstat res;
  1642. X    am_node *mp;
  1643. X    int retry;
  1644. X
  1645. X#ifdef DEBUG
  1646. X    Debug(D_TRACE)
  1647. X        plog(XLOG_DEBUG, "gettattr:");
  1648. X#endif
  1649. X
  1650. X    mp = fh_to_mp2(argp, &retry);
  1651. X    if (mp == 0) {
  1652. Xgetattr_retry:
  1653. X        if (retry < 0)
  1654. X            return 0;
  1655. X        res.status = nfs_error(retry);
  1656. X    } else {
  1657. X        if (mp->am_mnt->mf_fattr.type == NFLNK) {
  1658. X            /*
  1659. X             * Make sure we can read the link
  1660. X             */
  1661. X            char *ln = do_readlink(mp, &retry);
  1662. X            if (ln == 0)
  1663. X                goto getattr_retry;
  1664. X            mp->am_mnt->mf_fattr.size = strlen(ln);
  1665. X        }
  1666. X#ifdef DEBUG
  1667. X        Debug(D_TRACE)
  1668. X            plog(XLOG_DEBUG, "\tstat(%s), size = %d", mp->am_path, mp->am_mnt->mf_fattr.size);
  1669. X#endif
  1670. X        mp->am_stats.s_getattr++;
  1671. X        return &mp->am_mnt->mf_attr;
  1672. X    }
  1673. X
  1674. X    return &res;
  1675. X}
  1676. X
  1677. X
  1678. X/*ARGSUSED*/
  1679. Xstruct attrstat *
  1680. Xnfsproc_setattr_2(argp, rqstp)
  1681. Xstruct sattrargs *argp;
  1682. Xstruct svc_req *rqstp;
  1683. X{
  1684. X    static struct attrstat res;
  1685. X
  1686. X    if (!fh_to_mp(&argp->file))
  1687. X        res.status = nfs_error(ESTALE);
  1688. X    else
  1689. X        res.status = nfs_error(EROFS);
  1690. X
  1691. X    return &res;
  1692. X}
  1693. X
  1694. X
  1695. X/*ARGSUSED*/
  1696. Xvoidp 
  1697. Xnfsproc_root_2(argp, rqstp)
  1698. Xvoidp argp;
  1699. Xstruct svc_req *rqstp;
  1700. X{
  1701. X    static char res;
  1702. X
  1703. X    return (voidp)&res;
  1704. X}
  1705. X
  1706. X
  1707. X/*ARGSUSED*/
  1708. Xstruct diropres *
  1709. Xnfsproc_lookup_2(argp, rqstp)
  1710. Xstruct diropargs *argp;
  1711. Xstruct svc_req *rqstp;
  1712. X{
  1713. X    static struct diropres res;
  1714. X    am_node *mp;
  1715. X    int retry;
  1716. X
  1717. X#ifdef DEBUG
  1718. X    Debug(D_TRACE)
  1719. X        plog(XLOG_DEBUG, "lookup:");
  1720. X#endif
  1721. X
  1722. X    mp = fh_to_mp2(&argp->dir, &retry);
  1723. X    if (mp == 0) {
  1724. X        if (retry < 0)
  1725. X            return 0;
  1726. X        res.status = nfs_error(retry);
  1727. X    } else {
  1728. X        int error;
  1729. X        am_node *ap;
  1730. X#ifdef DEBUG
  1731. X        Debug(D_TRACE)
  1732. X            plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->name);
  1733. X#endif
  1734. X        ap = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &error, VLOOK_CREATE);
  1735. X        if (ap == 0) {
  1736. X            if (error < 0) {
  1737. X#ifdef DEBUG
  1738. X                dlog("Not sending RPC reply");
  1739. X#endif
  1740. X                amd_stats.d_drops++;
  1741. X                return 0;
  1742. X            }
  1743. X            res.status = nfs_error(error);
  1744. X        } else {
  1745. X#ifdef DEBUG
  1746. X            if (ap->am_mnt->mf_fattr.size < 0)
  1747. X                dlog("\tERROR: size = %d!", ap->am_mnt->mf_fattr.size);
  1748. X#endif
  1749. X            mp_to_fh(ap, &res.diropres_u.diropres.file);
  1750. X            res.diropres_u.diropres.attributes = ap->am_mnt->mf_fattr;
  1751. X            res.status = nfs_error(0);
  1752. X        }
  1753. X        mp->am_stats.s_lookup++;
  1754. X        /*reschedule_timeout_mp();*/
  1755. X    }
  1756. X
  1757. X    return &res;
  1758. X}
  1759. X
  1760. X
  1761. X/*ARGSUSED*/
  1762. Xstruct readlinkres *
  1763. Xnfsproc_readlink_2(argp, rqstp)
  1764. Xstruct nfs_fh *argp;
  1765. Xstruct svc_req *rqstp;
  1766. X{
  1767. X    static struct readlinkres res;
  1768. X    am_node *mp;
  1769. X    int retry;
  1770. X
  1771. X#ifdef DEBUG
  1772. X    Debug(D_TRACE)
  1773. X        plog(XLOG_DEBUG, "readlink:");
  1774. X#endif
  1775. X
  1776. X    mp = fh_to_mp2(argp, &retry);
  1777. X    if (mp == 0) {
  1778. X        if (retry < 0)
  1779. X            return 0;
  1780. X        res.status = nfs_error(retry);
  1781. X    } else {
  1782. X        char *ln = do_readlink(mp, &retry);
  1783. X        if (ln == 0) {
  1784. X            if (retry < 0)
  1785. X                return 0;
  1786. X            res.status = nfs_error(retry);
  1787. X        } else {
  1788. X            res.status = NFS_OK;
  1789. X        }
  1790. X#ifdef DEBUG
  1791. X        Debug(D_TRACE)
  1792. X            if (ln)
  1793. X                plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
  1794. X#endif
  1795. X        res.readlinkres_u.data = ln;
  1796. X        mp->am_stats.s_readlink++;
  1797. X    }
  1798. X
  1799. X    return &res;
  1800. X}
  1801. X
  1802. X
  1803. X/*ARGSUSED*/
  1804. Xstruct readres *
  1805. Xnfsproc_read_2(argp, rqstp)
  1806. Xstruct readargs *argp;
  1807. Xstruct svc_req *rqstp;
  1808. X{
  1809. X    static struct readres res;
  1810. X
  1811. X    bzero((char *)&res, sizeof(res));
  1812. X
  1813. X    res.status = nfs_error(EACCES);
  1814. X
  1815. X    return &res;
  1816. X}
  1817. X
  1818. X
  1819. X/*ARGSUSED*/
  1820. Xvoidp 
  1821. Xnfsproc_writecache_2(argp, rqstp)
  1822. Xvoidp argp;
  1823. Xstruct svc_req *rqstp;
  1824. X{
  1825. X    static char res;
  1826. X
  1827. X    return (voidp) &res;
  1828. X}
  1829. X
  1830. X
  1831. X/*ARGSUSED*/
  1832. Xstruct attrstat *
  1833. Xnfsproc_write_2(argp, rqstp)
  1834. Xwriteargs *argp;
  1835. Xstruct svc_req *rqstp;
  1836. X{
  1837. X    static struct attrstat res;
  1838. X
  1839. X    if (!fh_to_mp(&argp->file))
  1840. X        res.status = nfs_error(ESTALE);
  1841. X    else
  1842. X        res.status = nfs_error(EROFS);
  1843. X
  1844. X    return &res;
  1845. X}
  1846. X
  1847. X
  1848. X/*ARGSUSED*/
  1849. Xstruct diropres *
  1850. Xnfsproc_create_2(argp, rqstp)
  1851. Xcreateargs *argp;
  1852. Xstruct svc_req *rqstp;
  1853. X{
  1854. X    static struct diropres res;
  1855. X
  1856. X    if (!fh_to_mp(&argp->where.dir))
  1857. X        res.status = nfs_error(ESTALE);
  1858. X    else
  1859. X        res.status = nfs_error(EROFS);
  1860. X
  1861. X    return &res;
  1862. X}
  1863. X
  1864. X
  1865. X/*ARGSUSED*/
  1866. Xstatic nfsstat *
  1867. Xunlink_or_rmdir(argp, rqstp, unlinkp)
  1868. Xstruct diropargs *argp;
  1869. Xstruct svc_req *rqstp;
  1870. X{
  1871. X    static nfsstat res;
  1872. X    int retry;
  1873. X    mntfs *mf;
  1874. X    am_node *mp = fh_to_mp3(&argp->dir, &retry, VLOOK_DELETE);
  1875. X    if (mp == 0) {
  1876. X        if (retry < 0)
  1877. X            return 0;
  1878. X        res = nfs_error(retry);
  1879. X        goto out;
  1880. X    }
  1881. X    mf = mp->am_mnt;
  1882. X    if (mf->mf_fattr.type != NFDIR) {
  1883. X        res = nfs_error(ENOTDIR);
  1884. X        goto out;
  1885. X    }
  1886. X#ifdef DEBUG
  1887. X    Debug(D_TRACE)
  1888. X        plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->name);
  1889. X#endif
  1890. X    mp = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &retry, VLOOK_DELETE);
  1891. X    if (mp == 0) {
  1892. X        /*
  1893. X         * Ignore retries...
  1894. X         */
  1895. X        if (retry < 0)
  1896. X            retry = 0;
  1897. X        /*
  1898. X         * Usual NFS workaround...
  1899. X         */
  1900. X        else if (retry == ENOENT)
  1901. X            retry = 0;
  1902. X        res = nfs_error(retry);
  1903. X    } else {
  1904. X        forcibly_timeout_mp(mp);
  1905. X        res = NFS_OK;
  1906. X    }
  1907. X
  1908. Xout:
  1909. X    return &res;
  1910. X}
  1911. X
  1912. X
  1913. X/*ARGSUSED*/
  1914. Xnfsstat *
  1915. Xnfsproc_remove_2(argp, rqstp)
  1916. Xstruct diropargs *argp;
  1917. Xstruct svc_req *rqstp;
  1918. X{
  1919. X    return unlink_or_rmdir(argp, rqstp, 1);
  1920. X}
  1921. X
  1922. X/*ARGSUSED*/
  1923. Xnfsstat *
  1924. Xnfsproc_rename_2(argp, rqstp)
  1925. Xrenameargs *argp;
  1926. Xstruct svc_req *rqstp;
  1927. X{
  1928. X    static nfsstat res;
  1929. X    if (!fh_to_mp(&argp->from.dir) || !fh_to_mp(&argp->to.dir))
  1930. X        res = nfs_error(ESTALE);
  1931. X    else
  1932. X        res = nfs_error(EROFS);
  1933. X    return &res;
  1934. X}
  1935. X
  1936. X
  1937. X/*ARGSUSED*/
  1938. Xnfsstat *
  1939. Xnfsproc_link_2(argp, rqstp)
  1940. Xlinkargs *argp;
  1941. Xstruct svc_req *rqstp;
  1942. X{
  1943. X    static nfsstat res;
  1944. X    if (!fh_to_mp(&argp->from) || !fh_to_mp(&argp->to.dir))
  1945. X        res = nfs_error(ESTALE);
  1946. X    else
  1947. X        res = nfs_error(EROFS);
  1948. X
  1949. X    return &res;
  1950. X}
  1951. X
  1952. X
  1953. X/*ARGSUSED*/
  1954. Xnfsstat *
  1955. Xnfsproc_symlink_2(argp, rqstp)
  1956. Xsymlinkargs *argp;
  1957. Xstruct svc_req *rqstp;
  1958. X{
  1959. X    static nfsstat res;
  1960. X    if (!fh_to_mp(&argp->from.dir))
  1961. X        res = nfs_error(ESTALE);
  1962. X    else
  1963. X        res = nfs_error(EROFS);
  1964. X
  1965. X    return &res;
  1966. X}
  1967. X
  1968. X
  1969. X/*ARGSUSED*/
  1970. Xstruct diropres *
  1971. Xnfsproc_mkdir_2(argp, rqstp)
  1972. Xcreateargs *argp;
  1973. Xstruct svc_req *rqstp;
  1974. X{
  1975. X    static struct diropres res;
  1976. X    if (!fh_to_mp(&argp->where.dir))
  1977. X        res.status = nfs_error(ESTALE);
  1978. X    else
  1979. X        res.status = nfs_error(EROFS);
  1980. X
  1981. X    return &res;
  1982. X}
  1983. X
  1984. X
  1985. X/*ARGSUSED*/
  1986. Xnfsstat *
  1987. Xnfsproc_rmdir_2(argp, rqstp)
  1988. Xstruct diropargs *argp;
  1989. Xstruct svc_req *rqstp;
  1990. X{
  1991. X    return unlink_or_rmdir(argp, rqstp, 0);
  1992. X}
  1993. X
  1994. X
  1995. X/*ARGSUSED*/
  1996. Xstruct readdirres *
  1997. Xnfsproc_readdir_2(argp, rqstp)
  1998. Xreaddirargs *argp;
  1999. Xstruct svc_req *rqstp;
  2000. X{
  2001. X    static readdirres res;
  2002. X    static entry e_res[2];
  2003. X    am_node *mp;
  2004. X    int retry;
  2005. X
  2006. X#ifdef DEBUG
  2007. X    Debug(D_TRACE)
  2008. X        plog(XLOG_DEBUG, "readdir:");
  2009. X#endif
  2010. X
  2011. X    mp = fh_to_mp2(&argp->dir, &retry);
  2012. X    if (mp == 0) {
  2013. X        if (retry < 0)
  2014. X            return 0;
  2015. X        res.status = nfs_error(retry);
  2016. X    } else {
  2017. X#ifdef DEBUG
  2018. X        Debug(D_TRACE)
  2019. X            plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
  2020. X#endif
  2021. X        res.status = nfs_error((*mp->am_mnt->mf_ops->readdir)(mp, argp->cookie,
  2022. X                    &res.readdirres_u.reply, e_res));
  2023. X        mp->am_stats.s_readdir++;
  2024. X    }
  2025. X
  2026. X    /* XXX - need to take argp->count into account */
  2027. X
  2028. X    return &res;
  2029. X}
  2030. X
  2031. X/*ARGSUSED*/
  2032. Xstruct statfsres *
  2033. Xnfsproc_statfs_2(argp, rqstp)
  2034. Xstruct nfs_fh *argp;
  2035. Xstruct svc_req *rqstp;
  2036. X{
  2037. X    static statfsres res;
  2038. X    am_node *mp;
  2039. X    int retry;
  2040. X
  2041. X#ifdef DEBUG
  2042. X    Debug(D_TRACE)
  2043. X        plog(XLOG_DEBUG, "statfs:");
  2044. X#endif
  2045. X
  2046. X    mp = fh_to_mp2(argp, &retry);
  2047. X    if (mp == 0) {
  2048. X        if (retry < 0)
  2049. X            return 0;
  2050. X        res.status = nfs_error(retry);
  2051. X    } else {
  2052. X        statfsokres *fp;
  2053. X#ifdef DEBUG
  2054. X        Debug(D_TRACE)
  2055. X            plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
  2056. X#endif
  2057. X        /*
  2058. X         * just return faked up file system information
  2059. X         */
  2060. X
  2061. X        fp = &res.statfsres_u.reply;
  2062. X
  2063. X        fp->tsize = 1024;
  2064. X        fp->bsize = 4192;
  2065. X        fp->blocks = 0;
  2066. X        fp->bfree = 0;
  2067. X        fp->bavail = 0;
  2068. X
  2069. X        res.status = NFS_OK;
  2070. X        mp->am_stats.s_statfs++;
  2071. X    }
  2072. X
  2073. X    return &res;
  2074. X}
  2075. END_OF_FILE
  2076. if test 9501 -ne `wc -c <'nfs_stubs.c'`; then
  2077.     echo shar: \"'nfs_stubs.c'\" unpacked with wrong size!
  2078. fi
  2079. # end of 'nfs_stubs.c'
  2080. fi
  2081. if test -f 'rpc_fwd.c' -a "${1}" != "-c" ; then 
  2082.   echo shar: Will not clobber existing file \"'rpc_fwd.c'\"
  2083. else
  2084. echo shar: Extracting \"'rpc_fwd.c'\" \(8861 characters\)
  2085. sed "s/^X//" >'rpc_fwd.c' <<'END_OF_FILE'
  2086. X/*
  2087. X * $Id: rpc_fwd.c,v 5.1 89/11/17 18:22:04 jsp Exp Locker: jsp $
  2088. X *
  2089. X * Copyright (c) 1989 Jan-Simon Pendry
  2090. X * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  2091. X * Copyright (c) 1989 The Regents of the University of California.
  2092. X * All rights reserved.
  2093. X *
  2094. X * This code is derived from software contributed to Berkeley by
  2095. X * Jan-Simon Pendry at Imperial College, London.
  2096. X *
  2097. X * Redistribution and use in source and binary forms are permitted
  2098. X * provided that the above copyright notice and this paragraph are
  2099. X * duplicated in all such forms and that any documentation,
  2100. X * advertising materials, and other materials related to such
  2101. X * distribution and use acknowledge that the software was developed
  2102. X * by Imperial College of Science, Technology and Medicine, London, UK.
  2103. X * The names of the College and University may not be used to endorse
  2104. X * or promote products derived from this software without specific
  2105. X * prior written permission.
  2106. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  2107. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  2108. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  2109. X *
  2110. X *    %W% (Berkeley) %G%
  2111. X */
  2112. X
  2113. X/*
  2114. X * RPC packet forwarding
  2115. X */
  2116. X
  2117. X#include "am.h"
  2118. X#include <sys/ioctl.h>
  2119. X#ifndef F_SETFL
  2120. X#include <fcntl.h>
  2121. X#endif
  2122. X#ifndef FNDELAY
  2123. X#include <sys/file.h>
  2124. X#endif
  2125. X
  2126. X/*
  2127. X * Note that the ID field in the external packet is only
  2128. X * ever treated as a 32 bit opaque data object, so there
  2129. X * is no need to convert to and from network byte ordering.
  2130. X */
  2131. X
  2132. X/*
  2133. X * Each pending reply has an rpc_forward structure
  2134. X * associated with it.  These have a 15 second lifespan.
  2135. X * If a new structure is required, then an expired
  2136. X * one will be re-allocated if available, otherwise a fresh
  2137. X * one is allocated.  Whenever a reply is received the
  2138. X * structure is discarded.
  2139. X */
  2140. Xtypedef struct rpc_forward rpc_forward;
  2141. Xstruct rpc_forward {
  2142. X    qelem    rf_q;        /* Linked list */
  2143. X    time_t    rf_ttl;        /* Time to live */
  2144. X    u_int    rf_xid;        /* Packet id */
  2145. X    u_int    rf_oldid;    /* Original packet id */
  2146. X    fwd_fun    rf_fwd;        /* Forwarding function */
  2147. X    voidp    rf_ptr;
  2148. X    struct sockaddr_in rf_sin;
  2149. X};
  2150. X
  2151. X/*
  2152. X * Head of list of pending replies
  2153. X */
  2154. Xextern qelem rpc_head;
  2155. Xqelem rpc_head = { &rpc_head, &rpc_head };
  2156. X
  2157. Xstatic u_int xid;
  2158. X#define    XID_ALLOC()    (xid++)
  2159. X
  2160. X#define    MAX_PACKET_SIZE    8192    /* Maximum UDP packet size */
  2161. X
  2162. Xint fwd_sock;
  2163. X
  2164. X/*
  2165. X * Allocate a rely structure
  2166. X */
  2167. Xstatic rpc_forward *fwd_alloc()
  2168. X{
  2169. X    time_t now = clocktime();
  2170. X    rpc_forward *p = 0, *p2;
  2171. X
  2172. X#ifdef DEBUG
  2173. X    /*dlog("fwd_alloca: rpc_head = %#x", rpc_head.q_forw);*/
  2174. X#endif
  2175. X    /*
  2176. X     * First search for an existing expired one.
  2177. X     */
  2178. X    ITER(p2, rpc_forward, &rpc_head) {
  2179. X        if (p2->rf_ttl <= now) {
  2180. X            p = p2;
  2181. X            break;
  2182. X        }
  2183. X    }
  2184. X
  2185. X    /*
  2186. X     * If one couldn't be found then allocate
  2187. X     * a new structure and link it at the
  2188. X     * head of the list.
  2189. X     */
  2190. X    if (p) {
  2191. X        /*
  2192. X         * Call forwarding function to say that
  2193. X         * this message was junked.
  2194. X         */
  2195. X#ifdef DEBUG
  2196. X        dlog("Re-using packet forwarding slot - id %#x", p->rf_xid);
  2197. X#endif
  2198. X        if (p->rf_fwd)
  2199. X            (*p->rf_fwd)(0, 0, 0, &p->rf_sin, p->rf_ptr, FALSE);
  2200. X        rem_que(&p->rf_q);
  2201. X    } else {
  2202. X        p = ALLOC(rpc_forward);
  2203. X    }
  2204. X    ins_que(&p->rf_q, &rpc_head);
  2205. X
  2206. X    /*
  2207. X     * Set the time to live field
  2208. X     * Timeout in 43 seconds 
  2209. X     */
  2210. X    p->rf_ttl = now + 43;
  2211. X
  2212. X#ifdef DEBUG
  2213. X    /*dlog("fwd_alloca: rpc_head = %#x", rpc_head.q_forw);*/
  2214. X#endif
  2215. X    return p;
  2216. X}
  2217. X
  2218. X/*
  2219. X * Free an allocated reply structure.
  2220. X * First unlink it from the list, then
  2221. X * discard it.
  2222. X */
  2223. Xstatic void fwd_free(p)
  2224. Xrpc_forward *p;
  2225. X{
  2226. X#ifdef DEBUG
  2227. X    /*dlog("fwd_free: rpc_head = %#x", rpc_head.q_forw);*/
  2228. X#endif
  2229. X    rem_que(&p->rf_q);
  2230. X#ifdef DEBUG
  2231. X    /*dlog("fwd_free: rpc_head = %#x", rpc_head.q_forw);*/
  2232. X#endif
  2233. X    free(p);
  2234. X}
  2235. X
  2236. X/*
  2237. X * Initialise the RPC forwarder
  2238. X */
  2239. Xint fwd_init()
  2240. X{
  2241. X    int on = 1;
  2242. X
  2243. X    /*
  2244. X     * Create ping socket
  2245. X     */
  2246. X    fwd_sock = socket(AF_INET, SOCK_DGRAM, 0);
  2247. X    if (fwd_sock < 0) {
  2248. X        plog(XLOG_ERROR, "Unable to create RPC forwarding socket: %m");
  2249. X        return errno;
  2250. X    }
  2251. X
  2252. X    /*
  2253. X     * Some things we talk to require a priv port - so make one here
  2254. X     */
  2255. X    if (bind_resv_port(fwd_sock, (unsigned short *) 0) < 0)
  2256. X        plog(XLOG_ERROR, "can't bind privileged port");
  2257. X
  2258. X    if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0 &&
  2259. X            ioctl(fwd_sock, FIONBIO, &on) < 0) {
  2260. X        plog(XLOG_ERROR, "Can't set non-block on forwarding socket: %m");
  2261. X        return errno;
  2262. X    }
  2263. X
  2264. X    return 0;
  2265. X}
  2266. X
  2267. X/*
  2268. X * Locate a packet in the forwarding list
  2269. X */
  2270. Xstatic rpc_forward *fwd_locate(id)
  2271. Xu_int id;
  2272. X{
  2273. X    rpc_forward *p;
  2274. X
  2275. X    ITER(p, rpc_forward, &rpc_head) {
  2276. X        if (p->rf_xid == id)
  2277. X            return p;
  2278. X    }
  2279. X
  2280. X    return 0;
  2281. X}
  2282. X
  2283. X/*
  2284. X * This is called to forward a packet to another
  2285. X * RPC server.  The message id is changed and noted
  2286. X * so that when a reply appears we can tie it up
  2287. X * correctly.  Just matching the reply's source address
  2288. X * would not work because it might come from a
  2289. X * different address.
  2290. X */
  2291. Xint fwd_packet(type_id, pkt, len, fwdto, replyto, i, cb)
  2292. Xint type_id;
  2293. Xvoidp pkt;
  2294. Xint len;
  2295. Xstruct sockaddr_in *fwdto, *replyto;
  2296. Xvoidp i;
  2297. Xfwd_fun cb;
  2298. X{
  2299. X    rpc_forward *p;
  2300. X    u_int *pkt_int;
  2301. X    int error;
  2302. X
  2303. X    if ((int)amd_state >= (int)Finishing)
  2304. X        return ENOENT;
  2305. X
  2306. X    /*
  2307. X     * See if the type_id is fully specified.
  2308. X     * If so, then discard any old entries
  2309. X     * for this id.
  2310. X     * Otherwise make sure the type_id is
  2311. X     * fully qualified by allocating an id here.
  2312. X     */
  2313. X#ifdef DEBUG
  2314. X    switch (type_id & RPC_XID_MASK) {
  2315. X    case RPC_XID_PORTMAP: dlog("Sending PORTMAP request"); break;
  2316. X    case RPC_XID_MOUNTD: dlog("Sending MOUNTD request %#x", type_id); break;
  2317. X    case RPC_XID_NFSPING: dlog("Sending NFS ping"); break;
  2318. X    default: dlog("UNKNOWN RPC XID"); break;
  2319. X    }
  2320. X#endif
  2321. X
  2322. X    if (type_id & ~RPC_XID_MASK) {
  2323. X#ifdef DEBUG
  2324. X        /*dlog("Fully qualified rpc type provided");*/
  2325. X#endif
  2326. X        p = fwd_locate(type_id);
  2327. X        if (p) {
  2328. X#ifdef DEBUG
  2329. X            dlog("Discarding earlier rpc fwd handle");
  2330. X#endif
  2331. X            fwd_free(p);
  2332. X        }
  2333. X    } else {
  2334. X#ifdef DEBUG
  2335. X        dlog("Allocating a new xid...");
  2336. X#endif
  2337. X        type_id = MK_RPC_XID(type_id, XID_ALLOC());
  2338. X    }
  2339. X
  2340. X    p = fwd_alloc();
  2341. X    if (!p)
  2342. X        return ENOBUFS;
  2343. X
  2344. X    error = 0;
  2345. X
  2346. X    pkt_int = (u_int *) pkt;
  2347. X
  2348. X    /*
  2349. X     * Get the original packet id
  2350. X     */
  2351. X    p->rf_oldid = *pkt_int;
  2352. X
  2353. X    /*
  2354. X     * Replace with newly allocated id
  2355. X     */
  2356. X    p->rf_xid = *pkt_int = type_id;
  2357. X
  2358. X    /*
  2359. X     * The sendto may fail if, for example, the route
  2360. X     * to a remote host is lost because an intermediate
  2361. X     * gateway has gone down.  Important to fill in the
  2362. X     * rest of "p" otherwise nasty things happen later...
  2363. X     */
  2364. X#ifdef DEBUG
  2365. X    dlog("Sending packet id %#x to %#08x.%04x", p->rf_xid, ntohl(fwdto->sin_addr.s_addr), ntohs(fwdto->sin_port));
  2366. X#endif
  2367. X    if (sendto(fwd_sock, (char *) pkt, len, 0,
  2368. X            (struct sockaddr *) fwdto, sizeof(*fwdto)) < 0)
  2369. X        error = errno;
  2370. X
  2371. X    /*
  2372. X     * Save callback function and return address
  2373. X     */
  2374. X    p->rf_fwd = cb;
  2375. X    if (replyto)
  2376. X        p->rf_sin = *replyto;
  2377. X    else
  2378. X        bzero((voidp) &p->rf_sin, sizeof(p->rf_sin));
  2379. X    p->rf_ptr = i;
  2380. X
  2381. X    return error;
  2382. X}
  2383. X
  2384. X/*
  2385. X * Called when some data arrives on the forwarding socket
  2386. X */
  2387. Xvoid fwd_reply()
  2388. X{
  2389. X    int len;
  2390. X#ifdef DYNAMIC_BUFFERS
  2391. X    voidp pkt;
  2392. X#else
  2393. X    u_int pkt[MAX_PACKET_SIZE/sizeof(u_int)+1];
  2394. X#endif
  2395. X    u_int *pkt_int;
  2396. X    int rc;
  2397. X    rpc_forward *p;
  2398. X    struct sockaddr_in src_addr;
  2399. X    int src_addr_len;
  2400. X
  2401. X    /*
  2402. X     * Determine the length of the packet
  2403. X     */
  2404. X#ifdef DYNAMIC_BUFFERS
  2405. X    if (ioctl(fwd_sock, FIONREAD, &len) < 0) {
  2406. X        plog(XLOG_ERROR, "Error reading packet size: %m");
  2407. X        return;
  2408. X    }
  2409. X
  2410. X    /*
  2411. X     * Allocate a buffer
  2412. X     */
  2413. X    pkt = (voidp) malloc((unsigned) len);
  2414. X    if (!pkt) {
  2415. X        plog(XLOG_ERROR, "Out of buffers in fwd_reply");
  2416. X        return;
  2417. X    }
  2418. X#else
  2419. X    len = MAX_PACKET_SIZE;
  2420. X#endif
  2421. X
  2422. X    /*
  2423. X     * Read the packet and check for validity
  2424. X     */
  2425. Xagain:
  2426. X    src_addr_len = sizeof(src_addr);
  2427. X    rc = recvfrom(fwd_sock, (char *) pkt, len, 0,
  2428. X            (struct sockaddr *) &src_addr, &src_addr_len);
  2429. X    if (rc < 0 || src_addr_len != sizeof(src_addr) ||
  2430. X            src_addr.sin_family != AF_INET) {
  2431. X        if (rc < 0 && errno == EINTR)
  2432. X            goto again;
  2433. X        plog(XLOG_ERROR, "Error reading RPC reply: %m");
  2434. X        goto out;
  2435. X    }
  2436. X
  2437. X#ifdef DYNAMIC_BUFFERS
  2438. X    if (rc != len) {
  2439. X        plog(XLOG_ERROR, "Short read in fwd_reply");
  2440. X        goto out;
  2441. X    }
  2442. X#endif
  2443. X
  2444. X    /*
  2445. X     * Do no more work if finishing soon
  2446. X     */
  2447. X    if ((int)amd_state >= (int)Finishing)
  2448. X        goto out;
  2449. X
  2450. X    /*
  2451. X     * Find packet reference
  2452. X     */
  2453. X    pkt_int = (u_int *) pkt;
  2454. X
  2455. X#ifdef DEBUG
  2456. X    switch (*pkt_int & RPC_XID_MASK) {
  2457. X    case RPC_XID_PORTMAP: dlog("Receiving PORTMAP reply"); break;
  2458. X    case RPC_XID_MOUNTD: dlog("Receiving MOUNTD reply %#x", *pkt_int); break;
  2459. X    case RPC_XID_NFSPING: dlog("Receiving NFS ping %#x", *pkt_int); break;
  2460. X    default: dlog("UNKNOWN RPC XID"); break;
  2461. X    }
  2462. X#endif
  2463. X
  2464. X    p = fwd_locate(*pkt_int);
  2465. X    if (!p) {
  2466. X#ifdef DEBUG
  2467. X        dlog("Can't forward reply id %#x", *pkt_int);
  2468. X#endif
  2469. X        goto out;
  2470. X    }
  2471. X
  2472. X    if (p->rf_fwd) {
  2473. X        /*
  2474. X         * Put the original message id back
  2475. X         * into the packet.
  2476. X         */
  2477. X        *pkt_int = p->rf_oldid;
  2478. X
  2479. X        /*
  2480. X         * Call forwarding function
  2481. X         */
  2482. X        (*p->rf_fwd)(pkt, rc, &src_addr, &p->rf_sin, p->rf_ptr, TRUE);
  2483. X    }
  2484. X
  2485. X    /*
  2486. X     * Free forwarding info
  2487. X     */
  2488. X    fwd_free(p);
  2489. X
  2490. Xout:;
  2491. X#ifdef DYNAMIC_BUFFERS
  2492. X    /*
  2493. X     * Free the packet
  2494. X     */
  2495. X    free(pkt);
  2496. X#endif
  2497. X}
  2498. END_OF_FILE
  2499. if test 8861 -ne `wc -c <'rpc_fwd.c'`; then
  2500.     echo shar: \"'rpc_fwd.c'\" unpacked with wrong size!
  2501. fi
  2502. # end of 'rpc_fwd.c'
  2503. fi
  2504. echo shar: End of archive 6 \(of 13\).
  2505. cp /dev/null ark6isdone
  2506. MISSING=""
  2507. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
  2508.     if test ! -f ark${I}isdone ; then
  2509.     MISSING="${MISSING} ${I}"
  2510.     fi
  2511. done
  2512. if test "${MISSING}" = "" ; then
  2513.     echo You have unpacked all 13 archives.
  2514.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2515. else
  2516.     echo You still need to unpack the following archives:
  2517.     echo "        " ${MISSING}
  2518. fi
  2519. ##  End of shell archive.
  2520. exit 0
  2521. exit 0 # Just in case...
  2522.